package com.coolingme.notandor.expression;

import com.coolingme.notandor.IExpression;
import com.coolingme.notandor.expression.nonterminal.OrExpression;
import com.coolingme.notandor.expression.operator.AndOperator;
import com.coolingme.notandor.expression.operator.OrOperator;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 括号终结符表达式
 * <p>
 * 可能会包含多关键词组合，由大的表达式拆分为小的表达式
 * <p>
 * 如：(世博会|世界博览会)
 *
 * @author wangyue
 * @date 2022/12/25 21:54
 */
@Slf4j
public class BracketExpression implements IExpression {

    /**
     * 默认解析为
     */
    private OrExpression orExpression;

    /**
     * 表达式
     */
    private String expression;

    public BracketExpression(String expression) {
        this.expression = expression;
        // 解析表达式
        List<IExpression> iExpressionList = parseBracketExpression(expression);
        orExpression = new OrExpression(iExpressionList);
    }

    public String getExpression() {
        return expression;
    }

    @Override
    public Boolean interpret(String content) {
        Boolean result = orExpression.interpret(content);
        return result;
    }


    /**
     * 解析表达式，将表达式中 “并操作符”、“或操作符”、“括号终结符”和“单关键词终结符”分析为表达式列表
     * <p>
     * 如果包含括号等子表达式，使用递归解析子表达式
     *
     * @param expression 表达式
     * @return java.util.List<com.coolingme.notandor.IExpression> 抽象表达式列表
     * @author wangyue
     * @date 2022/12/26 22:52
     */
    private List<IExpression> parseBracketExpression(String expression) {
        log.info("------- 表达式：{} 解析开始-------", expression);
        // 括号表达式列表
        List<IExpression> bracketExpressionList = new ArrayList();

        // 匹配符号 | + ( )
        String patternRegex = "\\||\\+|\\-|\\(|\\)";
        Pattern r = Pattern.compile(patternRegex);
        Matcher m = r.matcher(expression);

        // 左括号的数量，出现右括号就相抵消
        int leftBracketOperatorNum = 0;
        String bracketExpression = "";

        // 单关键词
        int beginIndex = 0;
        int endIndex;

        // 匹配操作符
        while (m.find()) {
            if (0 == m.start()) {
                // 说明开头就命中操作符了，如果不是左括号，表示格式错误
                if (!"(".equals(m.group())) {
                    log.error("格式错误：{}", m.group());
                    break;
                }
            }

            endIndex = m.start();
            // 操作符中间的内容为字符串
            String keyword = expression.substring(beginIndex, endIndex).trim();
            if (!keyword.isEmpty()) {
                log.info("keyword:{}    beginIndex:{},endIndex,{}", keyword, beginIndex, endIndex);
                if (leftBracketOperatorNum == 0) {
                    bracketExpressionList.add(new KeywordExpression(keyword));
                } else {
                    bracketExpression += keyword;
                }
            }
            beginIndex = m.end();

            // 匹配到的符号
            String operator = m.group();
            log.info("{}          start:{},end:{}", operator, m.start(), m.end());
            if ("(".equals(operator)) {
                // 左括号个数+1
                leftBracketOperatorNum++;
                bracketExpression += operator;
            } else if (")".equals(operator)) {
                // 左括号个数-1
                --leftBracketOperatorNum;
                bracketExpression += operator;
                if (leftBracketOperatorNum == 0) {
                    // 左右括号相等时，加入到括号表达式列表
                    bracketExpressionList.add(new BracketExpression(bracketExpression.substring(1, bracketExpression.length() - 1)));
                    bracketExpression = "";
                }
            } else if ("+".equals(operator)) {
                // 没有左括号
                if (leftBracketOperatorNum == 0) {
                    bracketExpressionList.add(AndOperator.getInstance());
                } else {
                    bracketExpression += operator;
                }
            } else if ("|".equals(operator)) {
                if (leftBracketOperatorNum == 0) {
                    bracketExpressionList.add(OrOperator.getInstance());
                } else {
                    bracketExpression += operator;
                }
            }

        }

        if (beginIndex < expression.length()) {
            String keyword = expression.substring(beginIndex).trim();
            log.info("keyword:{}    beginIndex:{},endIndex,{}", keyword, beginIndex, expression.length());
            bracketExpressionList.add(new KeywordExpression(keyword));
        }
        log.info("------- 表达式：{} 解析完成-------\n", expression);

        return bracketExpressionList;
    }


}
